#ifndef LEAMINSTREAMHH
#define LEAMINSTREAMHH
#include "binary-in-stream.hh"
#include "leam-typedefs.hh"

namespace leam
{    
    class ILeamInStream
    {
    public:
	virtual ~ILeamInStream(){}
	//Some systems will send a read message out even when the system
	//really doesn't have any data.  This lets the user encasulate this
	//logic.  It is called during readNext, and readNext will return
	//instantly should this method return false.
	virtual bool hasData() = 0;
	virtual void operator>>( licada::uint8& val ) = 0;
	virtual void operator>>( licada::uint16& val ) = 0;
	//message id, length
	virtual void operator>>( licada::uint32& val ) = 0;
	//Write this as if it was a data vector, and don't write the null
	//character at the end.
	virtual void operator>> ( std::string& val ) = 0;
	virtual void operator>>( licada::TDataVector& val ) = 0;
	virtual void ignore( licada::uint32 numBytes ) = 0;
	virtual void close() = 0;
    };

    class LeamVectorInStream : public ILeamInStream, public licada::VectorBinaryInStream
    {
    public:
	LeamVectorInStream() {}
	virtual bool hasData() { return data != NULL && index < data->size(); }
	virtual void operator>>( licada::uint8& val ) { 
	    licada::VectorBinaryInStream::operator>>( val );
	}
	virtual void operator>>( licada::uint16& val ) { read( (licada::uint8*)&val, 2 ); }
	virtual void operator>>( licada::uint32& val ) { read( (licada::uint8*)&val, 4 ); }
	virtual void operator>>( std::string& val ) { 
	    using namespace licada;
	    uint32 end = val.length();
	    for( uint32 index = 0; index < end; ++index )
		val[index] = next();
	}
	virtual void operator>>( licada::TDataVector& val ) {
	    licada::VectorBinaryInStream::operator>>( val );
	}
	virtual void ignore( licada::uint32 numBytes ) {
	    index += numBytes;
	}
	virtual void close(){}
    private:
	licada::uint8 next() { licada::uint8 retval = data->at(index); ++index; return retval; }
    };
}
#endif
